<template>
<div class="echart-box">
    <h4 class="title-chart">{{option.title}}</h4>
    <div class="bar-line-box">
        <!-- 图表 -->
        <svg id="bar" class="ui-echart" :width="option.width" :height="option.height" v-html="DOM"></svg>
        <!-- 底部实例 -->
        <div id="labelList" class="label-list" v-html="reactdata.labelDOM"></div>
        <!-- 鼠标移上去的详情展示 -->
        <div id="detail" ref="detailVnode" v-show="reactdata.showDetail" v-html="reactdata.detailDOM" :style="reactdata.style"></div>
    </div>
</div>
</template>
<script setup>
import {onMounted, reactive, ref, nextTick, defineProps, computed, watch} from 'vue'
import {getYvalue} from '../../libs/fun.js'

let props = defineProps(['option'])
// 配置数据
let option = computed(() => {
  return {
    title:    props.option.title   || '', // 标题
    width:    props.option.width   || 600, // 图表款
    height:   props.option.height  || 400, // 图表高度
    bottom:   props.option.bottom  || 50, // x轴下边距
    left:     props.option.left    || 40, // y轴左边距
    yScale:   props.option.yScale  || 40, // y轴刻度宽度
    barWidth: props.option.barWidth|| 20, // 柱子宽度
    data: {
        xValue: props.option.data?.xValue||[],
        serve:  props.option.data?.serve ||[]
    }// 图表数据
  }
}) 
let detailVnode = ref(null)
// 双向绑定数据
let reactdata = reactive({
    showDetail: false,
    detailDOM:  '',
    labelDOM:   '',
    style:      {position: 'absolute'},
})
watch(option, () => { 
  DOM.value = ''
  barList = []
  lineList = []
  init()
  setTimeout(() => {handleOver()},500)
})


// 数据变量
let DOM = ref('')
let barList = []
let lineList = []
let idTime    = Math.random()*1000
const init = () => {
  reactdata.labelDOM = ''
  reactdata.showDetail = false
  let dotter    = option.value.height - option.value.bottom
  let xValue    = option.value.data.xValue||[]
  let xLength   = xValue.length
  let spanWidth = (option.value.width -option.value.left - 10)/xLength
  let valueList = [];
  let servList  = option.value.data.serve || [];servList.forEach(item => {valueList.push(...item.data)})
  let maxY      = Math.max(...valueList) === -Infinity ? 1 :Math.max(...valueList)
  let yLength   = Math.round(dotter/option.value.yScale)
  let yHeight   = dotter/yLength
  let yRowValue = getYvalue(maxY/yLength)
  barList   = servList.filter(item => item.type === 'bar')
  lineList  = servList.filter(item => item.type === 'line')
  let barLength = barList.length
  let barWidth  = option.value.barWidth > spanWidth/barLength ? spanWidth/barLength : option.value.barWidth
  let barLeft   = (spanWidth - barLength * barWidth)/2;
  // svg dom元素
  let barDOM    = '' // 柱状图html
  let lineDom   = '' // 折线图html
  let hoverDOM  = '' // hover区域html
  // 轴线DOM
  DOM.value = `<g id="barAxis">
          <line class="axis" x1="${option.value.left - 10}" y1="${dotter}" x2="${option.value.width}" y2="${dotter}"/>
          <line class="axis" x1="${option.value.left}" y1="0" x2="${option.value.left}" y2="${dotter + 10}"/>
          <polyline class="axis-arrow" points="${option.value.left-6},10 ${option.value.left},0 ${option.value.left+6},10 "/>
          <polyline class="axis-arrow" points="${option.value.width - 10},${dotter - 6} ${option.value.width},${dotter} ${option.value.width - 10},${dotter + 6} "/>
      </g>`
  // 添加svg DOM
  xValue.forEach((item, index) => {
     let i = Math.ceil(item.length*16 / spanWidth )
      // x轴刻度 x轴数值 鼠标热点区域
      DOM.value += 
          `<line class="axis" x1="${option.value.left+(index*spanWidth)}" y1="${dotter}" x2="${option.value.left+(index*spanWidth)}" y2="${dotter - 10}"/>
          <text x="${option.value.left+(index*spanWidth)+(spanWidth/2)}" y="${dotter+20}" style="text-anchor: middle;display:${index % i === 0? 'block':'none'}"><tspan>${item}</tspan></text>`
      hoverDOM+=`<rect class="bar-bg" width="${spanWidth}" height="${dotter}" x="${option.value.left+(index*spanWidth)}" y="0" data-index="${index}"/>`
      let barBoxDom = ''
      for (let i = 0; i < barList.length; i++) {
          const element = barList[i];
          let rato = element.data[index] || 0
          let barHeight = rato/yRowValue*yHeight
          let barX = option.value.left+barWidth*i + spanWidth*index + barLeft
          // 柱状图
          barBoxDom +=
          `<rect class="bar fill${i}" width="${barWidth}" height="0" x="${barX}" y="${dotter}">
              <animate attributeName="height" attributeType="XML" from="0"  to="${barHeight}" begin="0s" dur="0.3s" fill="freeze"/>
              <animate attributeName="y" attributeType="XML" from="${dotter}"  to="${option.value.height - barHeight - option.value.bottom}" begin="0s" dur="0.3s" fill="freeze"/>
          </rect>`;
      }
      barDOM +=`<g id="barBox${index}">${barBoxDom}</g>`
  })
  // 柱状图标签
  barList.forEach((item ,i) => {
      reactdata.labelDOM+=`<p class="label-bar-i label-bar label-bar${i}">${item.name}</p>`
  })
  // 折线图 折线图标签
  lineList.forEach((item, i) => {
      let pointer = '';
      let circleDOM = '';
      (item.data||[]).forEach((val, index) => {
          let lineXPoints = (1+index)*spanWidth-spanWidth/2+option.value.left
          let lineHeight = val/yRowValue*yHeight
          pointer += lineXPoints+','+ (dotter-lineHeight)+' ';
          circleDOM +=`<circle cx="${lineXPoints}" cy="${dotter-lineHeight}" r="2" class="polyline${i}" style="stroke-width:2px;fill:#ffffff"/>`
      })
      lineDom+=`<polyline class="polyline polyline${i}" points="${pointer}" fill="none"/>${circleDOM}`
      reactdata.labelDOM+=`<p class="label-line-i label-line label-line${i}">${item.name}</p>`
  })
  DOM.value += `<g id="barData">${barDOM}</g><g id="lineData">${lineDom}</g><g id="hoverDOM${idTime}">${hoverDOM}</g>`
  // y轴刻度 y轴数值
  for (let i = 1; i < yLength; i++) {
      DOM.value +=
          `<line class="axis" x1="${option.value.left-10}" y1="${yHeight*i}" x2="${option.value.left}" y2="${yHeight*i}"/>
          <text class="f12" x="0" y="${dotter - yHeight*i+4}"><tspan>${yRowValue < 1 ? (yRowValue*i).toFixed(2) : yRowValue*i}</tspan></text>`
  }
}
// 详细位置
let detailPosition = (event) => {
    nextTick(() => {
        let left = event.offsetX+15
        let top = event.offsetY+15
        let detailDOM = detailVnode.value
        let width = detailDOM.offsetWidth
        let height = detailDOM.offsetHeight
        if(left+width > option.value.width){
            reactdata.style.left = (left-width-30) +'px'
        }else{
            reactdata.style.left = left+'px'
        }
        if(top+height > option.value.height){
            reactdata.style.top = (top-height -30) +'px'
        }else{
            reactdata.style.top = top+'px'
        }
    })
}
init()

// 鼠标监听
const handleOver = () => {
    let hoverDOM = document.getElementById('hoverDOM'+idTime)
    hoverDOM.addEventListener('mouseover', (event) =>{
        let i = event.target.dataset.index
        let serveData = option.value.data
        let dataDom = '';
        barList.forEach((item, index) => {
            dataDom+= `<p class="flex label-bar label-bar${index}"><span>${item.name}</span>${item.data[i]}</p>`
        })
        lineList.forEach((item, index) => {
            dataDom+= `<p class="flex label-line label-line${index}"><span>${item.name}</span>${item.data[i]}</p>`
        })
        reactdata.detailDOM =
        `<div class="detail-box">
            <h4>${serveData.xValue[i]}</h4>
            ${dataDom}
        </div>`
        reactdata.showDetail = true
        detailPosition(event)
        console.log(reactdata);
        hoverDOM.onmousemove = (e) => {detailPosition(e)}
    })
    
    hoverDOM.addEventListener('mouseout', () =>{
        reactdata.showDetail = false
    })
}
// 监听鼠标事件
onMounted(() => {
  setTimeout(() => {handleOver()},500)
  
})

</script>
